﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using Meta.Numerics.Matrices;
using MR_HKSFilereader;

namespace MNTest
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length > 0)
            {

                //Loop over directory
                // Process the list of files found in the directory.
                string[] fileEntries = Directory.GetFiles(args[0]);
                foreach (string fileName in fileEntries)
                {

                    OffReader myOffReader;
                    myOffReader = new OffReader(fileName);
                    myOffReader.ReadFile();
                    myOffReader.LaplacianToFile();
                    /*
                    //1 Calculate Adjacency matrix
                    //2 Calculate Degree matrix

                    //3 Calculate Laplacian matrix
                    int[,] lMatrix = myOffReader.LaplacianMatrix();

                    //4 Calculate eigenvalues
                    //5 Calculate eigenvectors
                    SymmetricMatrix sq = new SymmetricMatrix(lMatrix.GetLength(0));
                    for (int i = 0; i < lMatrix.GetLength(0); i++)
                        for (int j = 0; j < lMatrix.GetLength(0); j++)
                            sq[i, j] = lMatrix[i, j];

                    double[,] mat = new double[sq.Dimension, sq.Dimension];
                    for (int i = 0; i < mat.GetLength(0); i++)
                        for (int j = 0; j < mat.GetLength(0); j++)
                            mat[i, j] = sq[i, j];
                    double[,] eigenvectors;
                    double[] eigenvalues;
                    alglib.smatrixevd(mat, mat.GetLength(0), 1, false, out eigenvalues, out eigenvectors);

                    //6 Calculate Kt(x,y)
                    List<double[]> eigenVectorsList = new List<double[]>();
                    List<double> eigenvaluesList = new List<double>();
                    List<double> cutev = new List<double>();
                    for (int i = 0; i < eigenvectors.GetLength(0); i++)
                        eigenvaluesList.Add(eigenvalues[i]);
                    eigenvaluesList.Sort();
                    double cutoff = eigenvaluesList[eigenvaluesList.Count - 300 - 1];
                    for (int i = 0; i < eigenvectors.GetLength(0); i++)
                        if (eigenvalues[i] >= cutoff)
                        {
                            double[] d = new double[eigenvectors.GetLength(0)];
                            for (int j = 0; j < d.Length; j++)
                                d[j] = eigenvectors[i, j];
                            eigenVectorsList.Add(d);
                            cutev.Add(eigenvalues[i]);
                        }

                    double[] fVectAtT = new double[cutev.Count];
                    double t = 0.1;
                    for (int i = 0; i < cutev.Count; i++)
                    {
                        fVectAtT[i] = HKT(i, t, eigenVectorsList, cutev);
                        Console.WriteLine(fVectAtT[i]);
                    }

                    //Storage class USAGE

                    Storage s = new Storage();

                    // Get off-file filename (e.g. 0006.sampling.5)
                    String offFileName = Path.GetFileNameWithoutExtension(fileName);

                    // save eigenvector
                    double[] eigenvectorsplusvalues = new double[eigenvalues.Length + eigenvectors.GetLength(0) * eigenvectors.GetLength(1)];
                    for (int i = 0; i < eigenvectors.GetLength(1); i++)
                        for (int j = 0; j < eigenvectors.GetLength(0); j++)
                            eigenvectorsplusvalues[j + i * eigenvectors.GetLength(0)] = eigenvectors[i, j];

                    for (int i = 0; i < eigenvalues.Length; i++)
                        eigenvectorsplusvalues[eigenvectors.Length + i] = eigenvalues[i];

                    s.saveEigenVector(offFileName, eigenvectorsplusvalues);

                    // Fetch data from saved files
                    //Console.WriteLine(s.getHKSValue(offFileName, 0.1));

                    double[] vector = s.getEigenVector(offFileName);
                    Console.WriteLine(vector[0] + " - " + vector[1] + " - " + vector[2]);

                    //7 Calc HKS for multiple times

                    //for (int i = 0 ; i < ce.Dimension; i++)
                    //{
                    //    Console.WriteLine("alg=" + eigenvalues[i] + " meta=" + ce.Eigenvalue(i));
                    //}

                    //Console.WriteLine("Size of dl: " + dl.Count + ", size of ce: " + ce.Dimension);
                    //double[] hks = HKS(0.0000001, 20, 0.1, ce);
                    //for (int i = 0; i < hks.Length; i++)
                    //    Console.WriteLine(hks[i]);

                    //double total = 0;
                    //for (int x = 0; x < eigenvectors.GetLength(0); x++)
                    //{
                    //    for (int i = 0; i < eigenvectors.GetLength(0); i++)
                    //    {
                    //        total += eigenvectors[i, x] * eigenvectors[i, x]; // ce.Eigenvector(i)[x] * ce.Eigenvector(i)[x];
                    //
                    //    }
                    //}
                    //total /= (double)ce.Dimension;
                    //Console.WriteLine("total = " + total);
                     * */
                }
            }
            else
                Console.WriteLine("No directory name given.");
        }

        private static double HKT(int x, double t, List<double[]> eigenvectors, List<double> eigenvalues)
        {
            double result = 0;
            for (int i = 0; i < eigenvectors.Count; i++)
            {
                result += (Math.Exp(-eigenvalues[i] * t) * eigenvectors[i][x] * eigenvectors[i][x]);
            }
            return result;
        }

     

       

    }
}
